package com.ruoyi.web.core.utils;

import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.stream.Collectors;

/**
 * 微信支付工具类
 * 
 * @author ruoyi
 */
@Component
public class WxPayUtils {
    
    private static final Logger logger = LoggerFactory.getLogger(WxPayUtils.class);
    
    /**
     * 解析微信支付回调通知
     * 
     * @param request HTTP请求
     * @param config RSA自动证书配置
     * @return 交易信息
     */
    public static Transaction parseNotification(HttpServletRequest request, RSAAutoCertificateConfig config) {
        try {
            // 获取请求体
            String body = getRequestBody(request);
            
            // 构建请求参数
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(request.getHeader("Wechatpay-Serial"))
                    .nonce(request.getHeader("Wechatpay-Nonce"))
                    .signature(request.getHeader("Wechatpay-Signature"))
                    .timestamp(request.getHeader("Wechatpay-Timestamp"))
                    .body(body)
                    .build();
            
            // 创建通知解析器
            NotificationParser parser = new NotificationParser(config);
            
            // 解析通知，返回交易信息
            return parser.parse(requestParam, Transaction.class);
            
        } catch (Exception e) {
            logger.error("解析微信支付回调通知失败", e);
            throw new RuntimeException("解析微信支付回调通知失败", e);
        }
    }
    
    /**
     * 获取请求体内容
     * 
     * @param request HTTP请求
     * @return 请求体字符串
     */
    private static String getRequestBody(HttpServletRequest request) throws IOException {
        try (BufferedReader reader = request.getReader()) {
            return reader.lines().collect(Collectors.joining(System.lineSeparator()));
        }
    }
    
    /**
     * 验证微信支付回调签名
     * 
     * @param request HTTP请求
     * @param config RSA自动证书配置
     * @return 是否验证通过
     */
    public static boolean verifySignature(HttpServletRequest request, RSAAutoCertificateConfig config) {
        try {
            parseNotification(request, config);
            return true;
        } catch (Exception e) {
            logger.warn("微信支付回调签名验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 生成随机字符串
     * 
     * @param length 长度
     * @return 随机字符串
     */
    public static String generateNonceStr(int length) {
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * chars.length());
            sb.append(chars.charAt(index));
        }
        return sb.toString();
    }
    
    /**
     * 生成订单号
     * 
     * @param prefix 前缀
     * @return 订单号
     */
    public static String generateOutTradeNo(String prefix) {
        return prefix + System.currentTimeMillis() + generateNonceStr(6);
    }
}